﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace PkwHCFramework.ResourceControls.Controls
{
    /// <summary>
    /// StatusTimeChart.xaml 的交互逻辑
    /// </summary>
    public partial class StatusTimeChart : UserControl
    {
        public StatusTimeChart()
        {
            InitializeComponent();
            Statuses = new ObservableCollection<StatusItem>();
        }

        public DateTime Date
        {
            get { return (DateTime)GetValue(DateProperty); }
            set { SetValue(DateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Date.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DateProperty = DependencyProperty.Register(
            "Date",
            typeof(DateTime),
            typeof(StatusTimeChart),
            new PropertyMetadata(DateTime.Today)
        );

        private Dictionary<string, Brush> statusColors = new Dictionary<string, Brush>();

        public ObservableCollection<StatusItem> Statuses
        {
            get { return (ObservableCollection<StatusItem>)GetValue(StatusesProperty); }
            set { SetValue(StatusesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Statuses.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StatusesProperty = DependencyProperty.Register(
            "Statuses",
            typeof(ObservableCollection<StatusItem>),
            typeof(StatusTimeChart),
            new PropertyMetadata(
                new ObservableCollection<StatusItem>(),
                (sender, e) =>
                {
                    var chart = sender as StatusTimeChart;
                    chart.StatusesChanged(sender, e);
                }
            )
        );

        void StatusesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null)
            {
                statusColors = Statuses.ToDictionary(x => x.Status, x => x.ShowColor);
            }
        }

        public IEnumerable<StatusTimeItem> ItemsSource
        {
            get { return (IEnumerable<StatusTimeItem>)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
            "ItemsSource",
            typeof(IEnumerable<StatusTimeItem>),
            typeof(StatusTimeChart),
            new PropertyMetadata(
                null,
                (sender, e) =>
                {
                    var chart = sender as StatusTimeChart;
                    chart.Update();
                }
            )
        );

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property.Name == "ItemsSource")
            {
                Update();
            }
            else if (e.Property.Name == "Statuses") { }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            statusColors = Statuses.ToDictionary(x => x.Status, x => x.ShowColor);
            DrawLedend();
        }

        void DrawLedend()
        {
            foreach (var item in Statuses)
            {
                Ellipse ellipse = new Ellipse
                {
                    Height = 12,
                    Width = 12,
                    Fill = item.ShowColor,
                };
                LegendPanel.Children.Add(ellipse);
                TextBlock textBlock = new TextBlock()
                {
                    Text = item.Text,
                    Foreground = Foreground,
                    Margin = new Thickness(2, 0, 5, 0),
                    FontSize = 12
                };
                LegendPanel.Children.Add(textBlock);
            }
        }

        /// <summary>
        /// 刻度线长
        /// </summary>
        private int length = 20;

        /// <summary>
        /// 刻度间隔
        /// </summary>
        private int intervalNum = 2;

        private int AreaNum = 6;

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            statusColors = Statuses.ToDictionary(x => x.Status, x => x.ShowColor);
            Update();
        }

        void Update()
        {
            this.ScaleCanvas.Children.Clear();
            GC.Collect();
            DrawContent();
            DrawScale();
        }

        //绘制设备运行状态时间图
        void DrawContent()
        {
            if (ItemsSource == null)
            {
                return;
            }
            double unit = ScaleCanvas.ActualWidth / (24 * 60);
            //根据ItemsSource筛选出当天的时间集合，然后绘制不同颜色的Rectangle
            var items = ItemsSource
                .Where(w => w.Time.Date.Equals(Date.Date) && statusColors.ContainsKey(w.Status))
                .ToArray();

            for (int i = 0; i < items.Length - 1; i++)
            {
                int start = GetMinutes(items[i].Time);
                int end = GetMinutes(items[i + 1].Time);
                Rectangle rectangle = new Rectangle
                {
                    Width = (end - start) * unit,
                    Height = ScaleCanvas.ActualHeight,
                    Fill = statusColors[items[i].Status]
                };
                rectangle.SetValue(Canvas.LeftProperty, start * unit);
                this.ScaleCanvas.Children.Add(rectangle);
            }
        }

        int GetMinutes(DateTime time)
        {
            return time.Hour * 60 + time.Minute;
        }

        /// <summary>
        /// 绘制刻度，根据canvas长度，分为24等分，对应24小时，刻度线长为length，最左边绘制0点
        /// </summary>
        void DrawScale()
        {
            double interval = ScaleCanvas.ActualWidth / 24 * intervalNum;
            double height = ScaleCanvas.ActualHeight;
            for (int i = 0; i <= 24 / intervalNum; i++)
            {
                double y1 = (i * intervalNum) % AreaNum == 0 ? 0 : height - length;
                y1 = Math.Min(Math.Abs(y1), height);

                Line line = new Line
                {
                    X1 = i * interval,
                    X2 = i * interval,
                    Y1 = y1,
                    Y2 = height,
                    Stroke = Brushes.Gray,
                    StrokeThickness = 1
                };
                this.ScaleCanvas.Children.Add(line);
                TextBlock textBlock = new TextBlock
                {
                    Text = (i * intervalNum).ToString(),
                    FontSize = FontSize,
                };
                textBlock.SetValue(Canvas.LeftProperty, i * interval - 5);
                textBlock.SetValue(Canvas.TopProperty, height);
                this.ScaleCanvas.Children.Add(textBlock);
            }
            ;
        }
    }

    public class StatusItem : DependencyObject
    {
        public string Status
        {
            get { return (string)GetValue(StatusProperty); }
            set { SetValue(StatusProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Status.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
            "Status",
            typeof(string),
            typeof(StatusItem),
            new PropertyMetadata("")
        );

        public Brush ShowColor
        {
            get { return (Brush)GetValue(ShowColorProperty); }
            set { SetValue(ShowColorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ShowColor.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ShowColorProperty = DependencyProperty.Register(
            "ShowColor",
            typeof(Brush),
            typeof(StatusItem),
            new PropertyMetadata(null)
        );

        /// <summary>
        /// 显示的文字
        /// </summary>
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
            "Text",
            typeof(string),
            typeof(StatusItem),
            new PropertyMetadata(null)
        );
    }
}
